"""
配置管理CLI命令

提供系统配置查看、修改等命令。
"""

import click
import json
import os
from pathlib import Path

from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.text import Text
from rich.syntax import Syntax

from src.bootstrap import get_service
from src.services.config_service import ConfigService


console = Console()


class ConfigCommand:
    """配置管理命令类"""

    def __init__(self):
        self.config_service = None

    def _get_config_service(self):
        """获取配置服务实例"""
        if not self.config_service:
            try:
                self.config_service = get_service(ConfigService)
            except Exception:
                # 如果无法获取服务，使用默认配置
                console.print("⚠️  无法连接到配置服务，使用默认配置", style="yellow")
                return None
        return self.config_service

    def _get_config_data(self):
        """获取配置数据"""
        config_service = self._get_config_service()
        if config_service:
            return config_service.get_all()
        else:
            # 备用默认配置
            return {
                'database': {'url': 'sqlite:///data/mixvideo.db'},
                'ai': {'gemini': {'api_key': ''}},
                'video': {'ffmpeg_path': '', 'opencv_enabled': True},
                'logging': {'level': 'INFO', 'file': 'logs/mixvideo.log'}
            }
    
    def register_commands(self, group):
        """注册命令到组"""
        # 直接注册命令函数，而不是方法
        @group.command()
        @click.option('--section', '-s', help='显示特定配置节')
        @click.option('--format', '-f', type=click.Choice(['table', 'json', 'yaml']), default='table', help='输出格式')
        def show(section, format):
            """显示当前配置"""
            return self.show_config(section, format)

        @group.command()
        @click.argument('key')
        @click.argument('value')
        @click.option('--type', '-t', type=click.Choice(['str', 'int', 'float', 'bool', 'json']), default='str', help='值类型')
        def set(key, value, type):
            """设置配置项"""
            return self.set_config(key, value, type)

        @group.command()
        @click.argument('key')
        @click.option('--default', '-d', help='默认值')
        def get(key, default):
            """获取配置项"""
            return self.get_config(key, default)

        @group.command()
        @click.option('--section', '-s', help='重置特定配置节')
        @click.option('--force', is_flag=True, help='强制重置（不询问确认）')
        def reset(section, force):
            """重置配置到默认值"""
            return self.reset_config(section, force)

        @group.command()
        def validate():
            """验证当前配置"""
            return self.validate_config()

        @group.command()
        @click.argument('output_file', type=click.Path())
        @click.option('--format', '-f', type=click.Choice(['json', 'yaml']), default='json', help='导出格式')
        @click.option('--section', '-s', help='导出特定配置节')
        def export(output_file, format, section):
            """导出配置到文件"""
            return self.export_config(output_file, format, section)

    def show_config(self, section, format):
        """显示当前配置"""
        console.print("⚙️  当前系统配置")

        try:
            # 获取实际的配置数据
            all_config_data = self._get_config_data()

            if section:
                config_data = all_config_data.get(section, {})
                if not config_data:
                    console.print(f"❌ 配置节不存在: {section}", style="red")
                    return
            else:
                config_data = all_config_data

            if format == 'json':
                syntax = Syntax(
                    json.dumps(config_data, indent=2, ensure_ascii=False),
                    "json",
                    theme="monokai",
                    line_numbers=True
                )
                console.print(syntax)
            elif format == 'yaml':
                try:
                    import yaml
                    syntax = Syntax(
                        yaml.dump(config_data, default_flow_style=False, allow_unicode=True),
                        "yaml",
                        theme="monokai",
                        line_numbers=True
                    )
                    console.print(syntax)
                except ImportError:
                    console.print("❌ PyYAML未安装，无法显示YAML格式", style="red")
            else:
                self._display_config_table(config_data, section)

        except Exception as e:
            console.print(f"❌ 显示配置失败: {e}", style="red")
    
    def _display_config_table(self, config_data, section_name=None):
        """显示配置表格"""
        if isinstance(config_data, dict):
            if section_name:
                title = f"配置节: {section_name}"
            else:
                title = "系统配置"
            
            table = Table(title=title, show_header=True, header_style="bold magenta")
            table.add_column("配置项", style="cyan", no_wrap=True)
            table.add_column("值", style="white")
            table.add_column("类型", style="dim")
            
            self._add_config_rows(table, config_data)
            console.print(table)
        else:
            console.print(f"配置值: [green]{config_data}[/green]")
    
    def _add_config_rows(self, table, config_data, prefix=""):
        """递归添加配置行"""
        for key, value in config_data.items():
            full_key = f"{prefix}.{key}" if prefix else key
            
            if isinstance(value, dict):
                # 嵌套配置，显示为节
                table.add_row(f"{full_key}.*", "[嵌套配置]", "dict")
                # 递归添加子项（限制深度）
                if len(prefix.split('.')) < 2:  # 最多2层深度
                    self._add_config_rows(table, value, full_key)
            elif isinstance(value, list):
                table.add_row(full_key, f"[{len(value)} 项]", "list")
            else:
                value_str = str(value)
                if len(value_str) > 50:
                    value_str = value_str[:47] + "..."
                table.add_row(full_key, value_str, type(value).__name__)
    
    def set_config(self, key, value, type):
        """
        设置配置项

        KEY: 配置键（支持点号分隔的嵌套键）
        VALUE: 配置值
        """
        console.print(f"⚙️  设置配置: [cyan]{key}[/cyan] = [green]{value}[/green]")

        try:
            # 类型转换
            if type == 'int':
                value = int(value)
            elif type == 'float':
                value = float(value)
            elif type == 'bool':
                value = value.lower() in ('true', '1', 'yes', 'on')
            elif type == 'json':
                value = json.loads(value)
            # str类型不需要转换

            # 使用配置服务设置配置
            config_service = self._get_config_service()
            if config_service:
                config_service.set(key, value)
                console.print(f"✅ 配置已更新: [cyan]{key}[/cyan]")
                console.print(f"   新值: [green]{value}[/green] ({type(value).__name__})")
            else:
                console.print("❌ 无法连接到配置服务", style="red")

        except ValueError as e:
            console.print(f"❌ 值类型转换失败: {e}", style="red")
        except Exception as e:
            console.print(f"❌ 设置配置失败: {e}", style="red")
    
    def get_config(self, key, default):
        """
        获取配置项

        KEY: 配置键
        """
        try:
            # 使用配置服务获取配置
            config_service = self._get_config_service()
            if config_service:
                value = config_service.get(key, default)
            else:
                # 备用方案：从本地配置数据获取
                keys = key.split('.')
                current = self._get_config_data()

                for k in keys:
                    if isinstance(current, dict) and k in current:
                        current = current[k]
                    else:
                        current = None
                        break

                value = current if current is not None else default

            if value is not None:
                console.print(f"📋 配置项: [cyan]{key}[/cyan]")
                console.print(f"   值: [green]{value}[/green]")
                console.print(f"   类型: [dim]{type(value).__name__}[/dim]")
            else:
                console.print(f"❌ 配置项不存在: {key}", style="yellow")
                if default:
                    console.print(f"   默认值: [dim]{default}[/dim]")

        except Exception as e:
            console.print(f"❌ 获取配置失败: {e}", style="red")
    
    def reset_config(self, section, force):
        """重置配置到默认值"""
        if section:
            console.print(f"⚠️  即将重置配置节: [yellow]{section}[/yellow]")
        else:
            console.print("⚠️  即将重置所有配置到默认值")
        
        if not force:
            if not click.confirm("确定要重置配置吗？"):
                console.print("❌ 操作已取消", style="yellow")
                return
        
        try:
            if section:
                # 重置特定节
                if section in self.config_data:
                    if section == 'database':
                        self.config_data[section] = {'url': 'sqlite:///data/mixvideo.db'}
                    elif section == 'ai':
                        self.config_data[section] = {'gemini': {'api_key': ''}}
                    elif section == 'video':
                        self.config_data[section] = {'ffmpeg_path': '', 'opencv_enabled': True}
                    elif section == 'logging':
                        self.config_data[section] = {'level': 'INFO', 'file': 'logs/mixvideo.log'}
                    console.print(f"✅ 配置节已重置: [green]{section}[/green]")
                else:
                    console.print(f"❌ 配置节不存在: {section}", style="red")
            else:
                # 重置所有配置
                self.config_data = {
                    'database': {'url': 'sqlite:///data/mixvideo.db'},
                    'ai': {'gemini': {'api_key': ''}},
                    'video': {'ffmpeg_path': '', 'opencv_enabled': True},
                    'logging': {'level': 'INFO', 'file': 'logs/mixvideo.log'}
                }
                console.print("✅ 所有配置已重置到默认值", style="green")

        except Exception as e:
            console.print(f"❌ 重置配置失败: {e}", style="red")
    
    def validate_config(self):
        """验证当前配置"""
        console.print("✅ 验证系统配置")

        try:
            # 使用配置服务验证
            config_service = self._get_config_service()
            if config_service:
                errors = config_service.validate_config()
                if not errors:
                    console.print("✅ 配置验证通过", style="green")
                    self._display_config_summary()
                else:
                    console.print("❌ 配置验证失败", style="red")
                    for error in errors:
                        console.print(f"  • {error}", style="red")
            else:
                # 备用验证逻辑
                config_data = self._get_config_data()
                warnings = []

                # 检查FFmpeg配置
                ffmpeg_config = config_data.get('ffmpeg', {})
                if not ffmpeg_config.get('binary_path'):
                    warnings.append("FFmpeg可执行文件路径未设置")

                # 检查AI配置
                ai_config = config_data.get('ai', {})
                if not ai_config.get('gemini', {}).get('api_key'):
                    warnings.append("Gemini API密钥未设置")

                console.print("✅ 配置验证通过", style="green")
                self._display_config_summary()

                # 显示警告
                for warning in warnings:
                    console.print(f"  ⚠️  {warning}", style="yellow")

        except Exception as e:
            console.print(f"❌ 验证失败: {e}", style="red")
    
    def _display_config_summary(self):
        """显示配置摘要"""
        try:
            config_data = self._get_config_data()

            summary_table = Table(title="配置摘要", show_header=False)
            summary_table.add_column("项目", style="cyan", no_wrap=True)
            summary_table.add_column("状态", style="white")

            # FFmpeg配置
            ffmpeg_config = config_data.get('ffmpeg', {})
            ffmpeg_status = "✅ 已配置" if ffmpeg_config.get('binary_path') else "❌ 未配置"
            summary_table.add_row("FFmpeg", ffmpeg_status)

            # AI配置
            ai_config = config_data.get('ai', {})
            ai_status = "✅ 已配置" if ai_config.get('gemini', {}).get('api_key') else "❌ 未配置"
            summary_table.add_row("AI服务", ai_status)

            # 视频处理配置
            opencv_config = config_data.get('opencv', {})
            opencv_status = "✅ 已配置" if opencv_config else "❌ 未配置"
            summary_table.add_row("视频处理", opencv_status)

            # 日志配置
            logging_config = config_data.get('logging', {})
            logging_status = "✅ 已配置" if logging_config.get('level') else "❌ 未配置"
            summary_table.add_row("日志系统", logging_status)

            console.print(summary_table)

        except Exception as e:
            console.print(f"⚠️  无法生成配置摘要: {e}", style="yellow")
    
    def export_config(self, output_file, format, section):
        """
        导出配置到文件

        OUTPUT_FILE: 输出文件路径
        """
        console.print(f"📤 导出配置到: [cyan]{output_file}[/cyan]")
        
        try:
            # 获取配置数据
            if section:
                config_data = self.config_data.get(section, {})
                if not config_data:
                    console.print(f"❌ 配置节不存在: {section}", style="red")
                    return
            else:
                config_data = self.config_data

            # 导出文件
            output_path = Path(output_file)
            output_path.parent.mkdir(parents=True, exist_ok=True)

            if format == 'yaml':
                try:
                    import yaml
                    with open(output_path, 'w', encoding='utf-8') as f:
                        yaml.dump(config_data, f, default_flow_style=False, allow_unicode=True)
                except ImportError:
                    console.print("❌ PyYAML未安装，无法导出YAML格式", style="red")
                    return
            else:
                with open(output_path, 'w', encoding='utf-8') as f:
                    json.dump(config_data, f, indent=2, ensure_ascii=False)

            console.print(f"✅ 配置已导出: [green]{output_file}[/green]")
            console.print(f"   格式: {format.upper()}")
            console.print(f"   大小: {output_path.stat().st_size} 字节")

        except Exception as e:
            console.print(f"❌ 导出失败: {e}", style="red")
    
    @click.command('import')
    @click.argument('input_file', type=click.Path(exists=True))
    @click.option('--section', '-s', help='导入到特定配置节')
    @click.option('--merge', is_flag=True, help='合并配置（而不是替换）')
    @click.option('--force', is_flag=True, help='强制导入（不询问确认）')
    def import_config(self, input_file, section, merge, force):
        """
        从文件导入配置
        
        INPUT_FILE: 输入文件路径
        """
        console.print(f"📥 从文件导入配置: [cyan]{input_file}[/cyan]")
        
        try:
            # 读取文件
            input_path = Path(input_file)
            
            if input_path.suffix.lower() in ['.yaml', '.yml']:
                import yaml
                with open(input_path, 'r', encoding='utf-8') as f:
                    config_data = yaml.safe_load(f)
            else:
                with open(input_path, 'r', encoding='utf-8') as f:
                    config_data = json.load(f)
            
            # 显示导入信息
            console.print(f"   文件格式: {input_path.suffix.upper()}")
            console.print(f"   配置项数: {len(config_data) if isinstance(config_data, dict) else 1}")
            
            if section:
                console.print(f"   目标节: {section}")
            
            if merge:
                console.print("   模式: 合并")
            else:
                console.print("   模式: 替换")
            
            # 确认导入
            if not force:
                if not click.confirm("确定要导入这些配置吗？"):
                    console.print("❌ 操作已取消", style="yellow")
                    return
            
            # 导入配置
            if section:
                if merge:
                    existing_config = self.config_data.get(section, {})
                    if isinstance(existing_config, dict) and isinstance(config_data, dict):
                        existing_config.update(config_data)
                        config_data = existing_config

                self.config_data[section] = config_data
            else:
                if merge:
                    if isinstance(self.config_data, dict) and isinstance(config_data, dict):
                        self.config_data.update(config_data)
                    else:
                        self.config_data = config_data
                else:
                    self.config_data = config_data
            
            console.print("✅ 配置导入成功", style="green")
            
        except Exception as e:
            console.print(f"❌ 导入失败: {e}", style="red")
    
    @click.command()
    def env(self):
        """显示环境变量配置"""
        console.print("🌍 环境变量配置")

        try:
            env_vars = [
                'MIXVIDEO_CONFIG_PATH',
                'MIXVIDEO_LOG_LEVEL',
                'MIXVIDEO_DATABASE_URL',
                'GEMINI_API_KEY',
                'FFMPEG_PATH',
                'OPENCV_PATH'
            ]

            env_table = Table(title="环境变量", show_header=True, header_style="bold magenta")
            env_table.add_column("变量名", style="cyan", no_wrap=True)
            env_table.add_column("值", style="white")
            env_table.add_column("状态", style="green")

            for var_name in env_vars:
                var_value = os.environ.get(var_name)
                if var_value:
                    # 隐藏敏感信息
                    if 'key' in var_name.lower() or 'password' in var_name.lower():
                        display_value = var_value[:8] + "..." if len(var_value) > 8 else var_value
                    else:
                        display_value = var_value

                    status = "✅ 已设置"
                else:
                    display_value = "未设置"
                    status = "❌ 未设置"

                env_table.add_row(var_name, display_value, status)

            console.print(env_table)

        except Exception as e:
            console.print(f"❌ 获取环境变量失败: {e}", style="red")
